﻿#region Copyright and License Notice
// Copyright (C)2010-2016 - Rob Levine and other contributors
// http://configgen.codeplex.com
// 
// This file is part of ConfigGen.
// 
// ConfigGen is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// ConfigGen is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License and 
// the GNU Lesser General Public License along with ConfigGen.  
// If not, see <http://www.gnu.org/licenses/>
#endregion

using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml;
using ConfigGen.Utilities;
using ConfigGen.Utilities.Extensions.System.Reflection;
using NUnit.Framework;

namespace ConfigGen.Core.Tests.EndToEndTests
{
    [TestFixture]
    public class CommandLineSwitchTests
    {
        /// <summary>
        /// Asserts that when the bare minimum of settings are specified (template file, settings file and output directory), the config-gen process works correctly.
        /// </summary>
        [Test]
        public void SettingTemplateAndOutputDirSpecfiedOnly()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string devAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\DevServer\\App.Config");
                string prodAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\ProdServer\\App.Config");
                string defaultAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\Default\\App.Config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                                   {
                                       TemplateFile = templateFile,
                                       SettingsFile = settingsFile,
                                       OutputDirectory = Path.Combine(testDirectory.FullName, "Configs")
                                   };

                var results = TestHelper.ExecuteCfgTest(settings);
             
                TestHelper.CheckExitResults(results, false);
                
                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");
                
                CheckDirectoriesAndFilesWereCreated(testDirectory, "Configs", devAppConfigPath, prodAppConfigPath, defaultAppConfigPath);
                CheckSimpleGeneratedConfigForDev(devAppConfigPath);
                CheckSimpleGeneratedConfigForProd(prodAppConfigPath);
                CheckSimpleGeneratedConfigForDefault(defaultAppConfigPath);
            }
        }

        /// <summary>
        /// Asserts that the correct exception is raised if the settings file is ommitted.
        /// </summary>
        [Test]
        public void SettingsFile001_ErrorIfMissing()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs")
                };

                var exception = Assert.Throws<PreferencesException>(() => TestHelper.ExecuteCfgTest(settings), "PreferencesException expected");
                Assert.IsNotNull(exception.FaultedSettings.FirstOrDefault(s=>string.Equals("SettingsFile", s, StringComparison.OrdinalIgnoreCase)), "SettingsFile expected as faulted setting");
            }
        }

        /// <summary>
        /// Asserts that the correct exception is raised if the template file is ommitted.
        /// </summary>
        [Test]
        public void TemplateFile001_ErrorIfMissing()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs")
                };

                var exception = Assert.Throws<PreferencesException>(() => TestHelper.ExecuteCfgTest(settings), "PreferencesException expected");
                Assert.IsNotNull(exception.FaultedSettings.FirstOrDefault(s => string.Equals("TemplateFile", s, StringComparison.OrdinalIgnoreCase)), "TemplateFile expected as faulted setting");
            }
        }


        /// <summary>
        /// Asserts that the correct exception is raised if the output directory is ommitted.
        /// </summary>
        [Test]
        public void OutputDirectory001_ErrorIfMissing()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile
                };

                var exception = Assert.Throws<PreferencesException>(() => TestHelper.ExecuteCfgTest(settings), "PreferencesException expected");
                Assert.IsNotNull(exception.FaultedSettings.FirstOrDefault(s => string.Equals("OutputDirectory", s, StringComparison.OrdinalIgnoreCase)), "OutputDirectory expected as faulted setting");
            }
        }

        [Test]
        public void FlatDirectoryOutput001()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                                   {
                                       SettingsFile = settingsFile,
                                       TemplateFile = templateFile,
                                       OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                                       FlatDirectoryOutput = true
                                   };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory should exist.");

                Assert.IsTrue(File.Exists(Path.Combine(testDirectory.FullName, "Configs\\App.Config")), "App.Config in configs directory not found");
                Assert.AreEqual(1, Directory.GetFiles(Path.Combine(testDirectory.FullName, "Configs")).Length, "Only one file expected in output directory");
            }
        }

        [Test]
        public void MachineSuffix001()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string devAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\DevServer\\App.Config.DevServer");
                string prodAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\ProdServer\\App.Config.ProdServer");
                string defaultAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\Default\\App.Config.Default");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    MachineSuffix = true
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");

                CheckDirectoriesAndFilesWereCreated(testDirectory, "Configs", devAppConfigPath, prodAppConfigPath, defaultAppConfigPath);
                CheckSimpleGeneratedConfigForDev(devAppConfigPath);
                CheckSimpleGeneratedConfigForProd(prodAppConfigPath);
                CheckSimpleGeneratedConfigForDefault(defaultAppConfigPath);
            }
        }

        [Test]
        public void ForcedFilename001()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string devAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\DevServer\\RenamedConfig.config");
                string prodAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\ProdServer\\RenamedConfig.config");
                string defaultAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\Default\\RenamedConfig.config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    ForcedFilename = "RenamedConfig.config"
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");

                CheckDirectoriesAndFilesWereCreated(testDirectory, "Configs", devAppConfigPath, prodAppConfigPath, defaultAppConfigPath);
                CheckSimpleGeneratedConfigForDev(devAppConfigPath);
                CheckSimpleGeneratedConfigForProd(prodAppConfigPath);
                CheckSimpleGeneratedConfigForDefault(defaultAppConfigPath);
            }
        }

        [Test]
        public void SpecifiedMachines001()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string prodAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\ProdServer\\App.Config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    SpecifiedMachines = new [] {"ProdServer"}
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");

                Assert.IsTrue(File.Exists(prodAppConfigPath), "App.Config in configs directory not found");
                Assert.AreEqual(1, Directory.GetDirectories(Path.Combine(testDirectory.FullName, "Configs")).Length, "One sub-directory expected in output directory");
            }
        }


        [Test]
        public void FilterMachinesByRegex001()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string prodAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\ProdServer\\App.Config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    MachineFilterExpression = @"(?<Environment>Prod)([a-zA-Z0-9_\\]+)" 
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");

                Assert.IsTrue(File.Exists(prodAppConfigPath), "App.Config in configs directory not found");
                Assert.AreEqual(1, Directory.GetDirectories(Path.Combine(testDirectory.FullName, "Configs")).Length, "One sub-directory expected in output directory");
            }
        }

        [Test]
        public void FilterMachinesByRegex002()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string prodAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\ProdServer\\App.Config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    MachineFilterExpression = @"([a-zA-Z0-9_\\]+)(?<Environment>Server)"
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");

                Assert.IsTrue(File.Exists(prodAppConfigPath), "App.Config in configs directory not found");
                Assert.AreEqual(2, Directory.GetDirectories(Path.Combine(testDirectory.FullName, "Configs")).Length, "One sub-directory expected in output directory");
            }
        }

        [Test]
        public void FilterMachinesByRegex003()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string prodAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\ProdServer\\App.Config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    MachineFilterExpression = @"(?<Environment>Prod)([a-zA-Z0-9_\\]+)",
                    SpecifiedMachines = new [ ]{"kdfgjkdg"}
                };

                Assert.Throws<ConfigurationErrorsException>(() => TestHelper.ExecuteCfgTest(settings));
                //var results = TestHelper.ExecuteCfgTest(settings);

                //TestHelper.CheckExitResults(results, false);

                //Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");

                //Assert.IsTrue(File.Exists(prodAppConfigPath), "App.Config in configs directory not found");
                //Assert.AreEqual(1, Directory.GetDirectories(Path.Combine(testDirectory.FullName, "Configs")).Length, "One sub-directory expected in output directory");
            }
        }

        [Test]
        public void LocalOnly001()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string defaultAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\Default\\App.Config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    LocalOnly = true
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");

                Assert.IsTrue(File.Exists(defaultAppConfigPath), "App.Config in configs directory not found");
                Assert.AreEqual(1, Directory.GetDirectories(Path.Combine(testDirectory.FullName, "Configs")).Length, "One sub-directory expected in output directory");
            }
        }

        [Test]
        public void InhibitWrite001()
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.Simple.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    InhibitWrite = true
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsFalse(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "ChangedOutputDir directory not found.");
            }
        }

        [Test]
        public void PrettyPrint001_PrettyPrintsWhenSpecified()
        {
            PrettyPrintTest(true);
        }

        [Test]
        public void PrettyPrint002_NoPrettyPrintWhenNotSpecified()
        {
            PrettyPrintTest(false);
        }

        public void PrettyPrintTest(bool prettyPrint)
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string defaultAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\Default\\App.Config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.PrettyPrint.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.PrettyPrint.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    PrettyPrint = prettyPrint
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                Assert.IsTrue(Directory.Exists(Path.Combine(testDirectory.FullName, "Configs")), "Configs directory not found.");

                CheckDirectoriesAndFilesWereCreated(testDirectory, "Configs", null, null, defaultAppConfigPath);

                string generatedFileContents = File.ReadAllText(defaultAppConfigPath);

                var lineNotWrappedRegex = new Regex(@"key=""Environment""[ \t]*value=""ThisIsAReallyLongLineOfTextThatIsDesignedToEnsureThatThePrettyPrintIsForcedToWrapToANewLine""");
                Console.WriteLine(generatedFileContents);

                if (prettyPrint)
                {
                    Assert.IsFalse(lineNotWrappedRegex.IsMatch(generatedFileContents), "With pretty-print on, the Environment appSetting element should have been wrapped");
                }
                else
                {
                    Assert.IsTrue(lineNotWrappedRegex.IsMatch(generatedFileContents), "With pretty-print off, the Environment appSetting element should not have been wrapped");
                }
            }
        }

        [Test]
        public void WriteUnchangedFiles001_OverwriteWhenSpecified()
        {
            WriteUnchangedFilesTest(true);
        }

        [Test]
        public void WriteUnchangedFiles002_NoOverwriteIfNotSpecified()
        {
            WriteUnchangedFilesTest(false);
        }

        public void WriteUnchangedFilesTest(bool writeUnchangedFiles)
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string defaultAppConfigPath = Path.Combine(testDirectory.FullName, "Configs\\Default\\App.Config");

                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.PrettyPrint.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.PrettyPrint.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    WriteUnchangedFiles = writeUnchangedFiles
                };

                TestHelper.ExecuteCfgTest(settings);
                DateTime generatedFileDateTime = File.GetLastWriteTimeUtc(defaultAppConfigPath);
                Thread.Sleep(1500);

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                DateTime reGeneratedFileDateTime = File.GetLastWriteTimeUtc(defaultAppConfigPath);

                if (writeUnchangedFiles)
                {
                    Assert.AreNotEqual(generatedFileDateTime, reGeneratedFileDateTime,
                    "Creation DateTime of config file should change on second run as WriteUnchangedFiles was specified.");
                }
                else
                {
                    Assert.AreEqual(generatedFileDateTime, reGeneratedFileDateTime,
                                    "Creation DateTime of config file should not change on second run as it should not have been written a second time (WriteUnchangedFiles not specified).");
                }
            }
        }

        [Test]
        public void RemoveRootElement001_RootElementRemovedWhenSpecified()
        {
            RemoveRootElementTest(true);
        }

        [Test]
        public void RemoveRootElement002_RootElementNotRemovedWhenNotSpecified()
        {
            RemoveRootElementTest(false);
        }

        public void RemoveRootElementTest(bool removeRootElement)
        {
            using (var testDirectory = new DisposableDirectory())
            {
                string settingsFile = Path.Combine(testDirectory.FullName, "App.Config.Settings.xls");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.RemoveRootElement.App.Config.Settings.xls", settingsFile);

                string templateFile = Path.Combine(testDirectory.FullName, "App.Config.Template.xml");
                Assembly.GetExecutingAssembly().CopyEmbeddedResourceFileTo("TestResources.RemoveRootElement.App.Config.Template.xml", templateFile);

                var settings = new Preferences
                {
                    SettingsFile = settingsFile,
                    TemplateFile = templateFile,
                    OutputDirectory = Path.Combine(testDirectory.FullName, "Configs"),
                    RemoveRootElement = removeRootElement
                };

                var results = TestHelper.ExecuteCfgTest(settings);

                TestHelper.CheckExitResults(results, false);

                var dom = new XmlDocument();
                dom.Load(results.First().GeneratedFile.FullName);

                if (removeRootElement)
                {
                    Assert.AreEqual("appSettings", dom.DocumentElement.LocalName, "Original root element should have been removed. Got unexpected root element name.");
                }
                else
                {
                    Assert.AreEqual("rootElement", dom.DocumentElement.LocalName, "Original root element should not have been removed. Got unexpected root element name.");
                }
            }
        }

        private void CheckDirectoriesAndFilesWereCreated(DisposableDirectory testDirectory, string outputDirectoryName, string devAppConfigPath, string prodAppConfigPath, string defaultAppConfigPath)
        {
            if (devAppConfigPath != null)
            {
                Assert.IsTrue(
                    Directory.Exists(Path.Combine(testDirectory.FullName, outputDirectoryName + "\\DevServer")),
                    "DevServer config file directory not found.");
                Assert.IsTrue(File.Exists(devAppConfigPath), "DevServer config file not found");
            }

            if (prodAppConfigPath != null)
            {
                Assert.IsTrue(
                    Directory.Exists(Path.Combine(testDirectory.FullName, outputDirectoryName + "\\ProdServer")),
                    "ProdServer config file directory not found.");
                Assert.IsTrue(File.Exists(prodAppConfigPath), "ProdServer config file not found");
            }

            if (defaultAppConfigPath != null)
            {
                Assert.IsTrue(
                    Directory.Exists(Path.Combine(testDirectory.FullName, outputDirectoryName + "\\Default")),
                    "Default config file directory not found.");
                Assert.IsTrue(File.Exists(defaultAppConfigPath), "Default config file not found");
            }
        }

        private void CheckSimpleGeneratedConfigForDev(string devAppConfigPath)
        {
            var devAppConfig = new XmlDocument();
            devAppConfig.Load(devAppConfigPath);
            XmlNode environmentNode = devAppConfig.SelectSingleNode("/configuration/appSettings/add[@key='Environment']/@value");
            Assert.IsNotNull(environmentNode, "Environment appSetting not found for Dev");
            Assert.AreEqual("DEV", environmentNode.Value, "Incorrect environment value for Dev");
            XmlNode customErrorsModeNode = devAppConfig.SelectSingleNode("//customErrors/@mode");
            Assert.IsNotNull(customErrorsModeNode, "customErrors mode not found for Dev");
            Assert.AreEqual("RemoteOnly", customErrorsModeNode.Value, "Incorrect customErrors mode value for Dev");
            Assert.IsNotNull(devAppConfig.SelectSingleNode("//customErrors/error"), "customErrors/error element was expected for Dev");
        }

        private void CheckSimpleGeneratedConfigForProd(string prodAppConfigPath)
        {
            XmlNode environmentNode;
            XmlNode customErrorsModeNode;
            var prodAppConfig = new XmlDocument();
            prodAppConfig.Load(prodAppConfigPath);
            environmentNode = prodAppConfig.SelectSingleNode("/configuration/appSettings/add[@key='Environment']/@value");
            Assert.IsNotNull(environmentNode, "Environment appSetting not found for Prod");
            Assert.AreEqual("PROD", environmentNode.Value, "Incorrect environment value for Prod");
            customErrorsModeNode = prodAppConfig.SelectSingleNode("//customErrors/@mode");
            Assert.IsNotNull(customErrorsModeNode, "customErrors mode not found for Prod");
            Assert.AreEqual("On", customErrorsModeNode.Value, "Incorrect customErrors mode value for Prod");
            Assert.IsNotNull(prodAppConfig.SelectSingleNode("//customErrors/error"), "customErrors/error element was expected for Prod");
        }

        private void CheckSimpleGeneratedConfigForDefault(string defaultAppConfigPath)
        {
            XmlNode environmentNode;
            XmlNode customErrorsModeNode;
            var defaultAppConfig = new XmlDocument();
            defaultAppConfig.Load(defaultAppConfigPath);
            environmentNode = defaultAppConfig.SelectSingleNode("/configuration/appSettings/add[@key='Environment']/@value");
            Assert.IsNotNull(environmentNode, "Environment appSetting not found for Default");
            Assert.AreEqual("DEV", environmentNode.Value, "Incorrect environment value for Default");
            customErrorsModeNode = defaultAppConfig.SelectSingleNode("//customErrors/@mode");
            Assert.IsNotNull(customErrorsModeNode, "customErrors mode not found for Default");
            Assert.AreEqual("Off", customErrorsModeNode.Value, "Incorrect customErrors mode value for Default");
            Assert.IsNull(defaultAppConfig.SelectSingleNode("//customErrors/error"), "customErrors/error element was not expected for Default");
        }
    }
}
